package com.authstr.support;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 用于构建sql语句
 */
public class BuildSql {

    /**
     * 主键 字段名
     */
    public static  final String PRIMARY_KEY="id";

    /**
     * 主键 使用uuid的sql
     */
    public static  final String USER_UUID=" REPLACE (uuid(), '-', '') ";


    /**
     * 操作的表名
     */
    private String tableName;

    /**
     * 指定的唯一键
     */
    private String[] uniqueColumn;


    /**
     * 是否在语句前添加注释 默认true
     */
    private Boolean enableAddAnnotation=true;


    /**
     * 在创建插入语句时,id是否使用生成的UUID,默认使用原id.  默认false
     */
    private Boolean enableUserUUIDOnInsert=false;

    /**
     * 在创建插入语句时,是否先创建删除语句(以Id为限制条件) 默认false
     */
    private Boolean enableDelectByIdOnInsert=false;


    /**
     * 在创建插入语句时,是否先创建删除语句(以唯一键为限制条件)    默认false
     */
    private Boolean enableDelectByUniqueOnInsert=false;

    /**
     * 在创建更新时,对于值一样的数据,是否也写在更新语句中  默认false
     */
    private Boolean enableUpdateSameOnUpdate=false;


    /**
     * 在创建更新时,是否先创建删除语句(以Id为限制条件) 默认false
     */
    private Boolean enableDelectByIdOnUpdate=false;

    /**
     * 在创建更新时,是否先创建删除语句(以唯一键为限制条件)    默认false
     */
    private Boolean enableDelectByUniqueOnUpdate=false;

    /**
     * 在创建更新时,是否以插入语句来进行修改  默认false
     */
    private Boolean enableChangeInsertOnUpdate=true;

    /**
     * 在创建更新时,插入语句是否使用UUID  默认false
     */
    private Boolean enableUserUUIDOnUpdate=true;

    /**
     * 删除语句是否以唯一键作为限制条件进行创建(默认使用id) 默认false
     */
    private Boolean enableUserUniqueDelete=false;

    public  BuildSql(String tableName,String...uniqueColumn){
        this.tableName=tableName;
        this.uniqueColumn=uniqueColumn;
    }




    /**
     * 创建一条数据所需要的插入语句
     * @param uniqueValue
     * @param data
     * @return
     */
    public List<String> createInsertSql(String[] uniqueValue,Map<String,Object> data){
        List<String> res=new ArrayList<String>();
        if(enableAddAnnotation){
            res.add(CreateAnnotation.insertTipText(uniqueColumn,uniqueValue));
        }

        if(enableDelectByIdOnInsert){
            //删除注释
            if(enableAddAnnotation){
                String temp=CreateAnnotation.operationTipText(new String[]{PRIMARY_KEY},new String[]{data.get(PRIMARY_KEY).toString()},"先删除数据");
                res.add(CreateAnnotation.textAddOneTab(temp));
            }
            //加一缩进
            String delectById=onlyCreateDeleteSqlById(data.get(PRIMARY_KEY).toString());
            res.add(CreateAnnotation.textAddOneTab(delectById));
        }

        if(enableDelectByUniqueOnInsert){
            //删除注释
            if(enableAddAnnotation){
                String temp=CreateAnnotation.operationTipText(uniqueColumn,uniqueValue,"先删除数据");
                res.add(CreateAnnotation.textAddOneTab(temp));
            }
            //加一缩进
            String delectByUnique=onlyCreateDeleteSqlByUnique(uniqueValue);
            res.add(CreateAnnotation.textAddOneTab(delectByUnique));
        }
        res.add(onlyCreateInsertSql(data,enableUserUUIDOnInsert));
        return res;
    }

    public List<String> createUpdateSql(String[] uniqueValue,List<String> updateColumn,Map<String,Object> newData,Map<String,Object> oldData){
        List<String> res=new ArrayList<String>();
        if(enableAddAnnotation){
            res.add(CreateAnnotation.updateTipText(uniqueColumn,uniqueValue));
        }

        if(enableDelectByIdOnUpdate){
            //删除注释
            if(enableAddAnnotation){
                String temp=CreateAnnotation.operationTipText(new String[]{PRIMARY_KEY},new String[]{newData.get(PRIMARY_KEY).toString()},"先删除数据");
                res.add(CreateAnnotation.textAddOneTab(temp));
            }
            //加一缩进
            String delectById=onlyCreateDeleteSqlById(newData.get(PRIMARY_KEY).toString());
            res.add(CreateAnnotation.textAddOneTab(delectById));
        }

        if(enableDelectByUniqueOnUpdate){
            //删除注释
            if(enableAddAnnotation){
                String temp=CreateAnnotation.operationTipText(uniqueColumn,uniqueValue,"先删除数据");
                res.add(CreateAnnotation.textAddOneTab(temp));
            }
            //加一缩进
            String delectByUnique=onlyCreateDeleteSqlByUnique(uniqueValue);
            res.add(CreateAnnotation.textAddOneTab(delectByUnique));
        }

        if(enableChangeInsertOnUpdate){
            res.add(onlyCreateInsertSql(newData,enableUserUUIDOnUpdate));
        }else{
            res.add(onlyCreateUpdateSql(updateColumn,newData,oldData));
        }
        return res;
    }

    /**
     * 创建一条数据所需要的删除语句
     * @param uniqueValue
     * @param data
     * @return
     */
    public List<String> createDeleteSql(String[] uniqueValue,Map<String,Object> data){
        List<String> res=new ArrayList<String>();
        //删除语句是否以唯一键作为限制条件进行创建
        if(enableUserUniqueDelete){
            if(enableAddAnnotation){
                res.add(CreateAnnotation.operationTipText(uniqueColumn,uniqueValue,"删除(通过指定列)"));
            }
            res.add(onlyCreateDeleteSqlByUnique(uniqueValue));
        }else{
            if(enableAddAnnotation){
                res.add(CreateAnnotation.operationTipText(uniqueColumn,uniqueValue,"删除(通过id)"));
            }
            res.add(onlyCreateDeleteSqlById(data.get(PRIMARY_KEY).toString()));
        }

        return res;
    }


    /**
     * 仅创建一条插入语句
     * @param data
     * @return
     */
    public String onlyCreateInsertSql(Map<String,Object> data,Boolean isUserUUID){
        StringBuffer res = new StringBuffer();
        res.append(" INSERT INTO ").append(tableName).append(" ( ");

        //用于记录拼接的值
        StringBuffer value_joint = new StringBuffer();
        //用于循环计数
        int order=1;

        for (String key: data.keySet()) {
            //拼接插入键
            res.append("`").append(key).append("`");

            //如果当前是id,且需要使用生成UUID
            if(key.equals(PRIMARY_KEY) && isUserUUID){
                value_joint.append(USER_UUID);
            }else{
                //拼接插入值
                Object value=data.get(key);
                if(null!=value){
                    value_joint.append("'").append(value).append("'");
                }else{
                    value_joint.append("null");
                }
            }


            //如果当前不是最后一个列,在键和值列表 拼接上","
            if(order!=data.keySet().size()){
                res.append(",");
                value_joint.append(",");
            }
            order++;
        }
        res.append("  ) VALUES ( ").append(value_joint).append(" );");
        return res.toString();
    }

    /**
     * 仅创建一条更新语句
     * @param updateColumn
     * @param newData
     * @param oldData
     * @return
     */
    public String onlyCreateUpdateSql(List<String> updateColumn,Map<String,Object> newData,Map<String,Object> oldData){
        StringBuffer res = new StringBuffer();
        res.append(" UPDATE ").append(tableName).append(" SET ");
        for(int i=0;i<updateColumn.size();i++){
            String key=updateColumn.get(i);
            Object newValue=newData.get(updateColumn.get(i));
            Object oldValue=oldData.get(updateColumn.get(i));
            //如果值相等,且 不是 相等也生成 跳过
            if(!enableUpdateSameOnUpdate&&CommonUtil.isSame(newValue,oldValue)){
                continue;
            }
            res.append("`").append(key).append("` = ");

            if(null!=newValue){
                res.append("'").append(newValue).append("'");
            }else{
                res.append("null");
            }
            if(i!=(updateColumn.size()-1)){
                res.append(" , ");
            }
        }
        res.append(" WHERE ").append("`").append(PRIMARY_KEY).append("`").append("=").append("'").append(oldData.get(PRIMARY_KEY)).append("' ;");
        return res.toString();
    }



    /**
     * 通过id值,创建删除语句
     * @param primaryKeyValue id的值
     * @return
     */
    public String onlyCreateDeleteSqlById(String primaryKeyValue){
        return onlyCreateDeleteSql(new String[]{PRIMARY_KEY},new String[]{primaryKeyValue});
    }

    /**
     * 通过唯一列,创建删除语句
     * @param uniqueValue  唯一列的值
     * @return
     */
    public String onlyCreateDeleteSqlByUnique(String[] uniqueValue){
        return onlyCreateDeleteSql(uniqueColumn,uniqueValue);
    }

    /**
     * 通过指定的键和值,创建删除语句
     * @param key
     * @param value
     * @return
     */
    public String onlyCreateDeleteSql(String[] key,String[] value){
        StringBuffer res = new StringBuffer();
        res.append(" DELETE FROM ").append(tableName).append(" WHERE 1=1 ");
        for(int i=0;i<key.length;i++){
            res.append(" and ").append("`").append(key[i]).append("`").append(" = ").append("'").append(value[i]).append("' ;");
        }
        return res.toString();
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String[] getUniqueColumn() {
        return uniqueColumn;
    }

    public void setUniqueColumn(String[] uniqueColumn) {
        this.uniqueColumn = uniqueColumn;
    }

    public Boolean getEnableAddAnnotation() {
        return enableAddAnnotation;
    }

    public void setEnableAddAnnotation(Boolean enableAddAnnotation) {
        this.enableAddAnnotation = enableAddAnnotation;
    }

    public Boolean getEnableUserUUIDOnInsert() {
        return enableUserUUIDOnInsert;
    }

    public void setEnableUserUUIDOnInsert(Boolean enableUserUUIDOnInsert) {
        this.enableUserUUIDOnInsert = enableUserUUIDOnInsert;
    }

    public Boolean getEnableDelectByIdOnInsert() {
        return enableDelectByIdOnInsert;
    }

    public void setEnableDelectByIdOnInsert(Boolean enableDelectByIdOnInsert) {
        this.enableDelectByIdOnInsert = enableDelectByIdOnInsert;
    }

    public Boolean getEnableDelectByUniqueOnInsert() {
        return enableDelectByUniqueOnInsert;
    }

    public void setEnableDelectByUniqueOnInsert(Boolean enableDelectByUniqueOnInsert) {
        this.enableDelectByUniqueOnInsert = enableDelectByUniqueOnInsert;
    }

    public Boolean getEnableUpdateSameOnUpdate() {
        return enableUpdateSameOnUpdate;
    }

    public void setEnableUpdateSameOnUpdate(Boolean enableUpdateSameOnUpdate) {
        this.enableUpdateSameOnUpdate = enableUpdateSameOnUpdate;
    }

    public Boolean getEnableDelectByIdOnUpdate() {
        return enableDelectByIdOnUpdate;
    }

    public void setEnableDelectByIdOnUpdate(Boolean enableDelectByIdOnUpdate) {
        this.enableDelectByIdOnUpdate = enableDelectByIdOnUpdate;
    }

    public Boolean getEnableDelectByUniqueOnUpdate() {
        return enableDelectByUniqueOnUpdate;
    }

    public void setEnableDelectByUniqueOnUpdate(Boolean enableDelectByUniqueOnUpdate) {
        this.enableDelectByUniqueOnUpdate = enableDelectByUniqueOnUpdate;
    }

    public Boolean getEnableChangeInsertOnUpdate() {
        return enableChangeInsertOnUpdate;
    }

    public void setEnableChangeInsertOnUpdate(Boolean enableChangeInsertOnUpdate) {
        this.enableChangeInsertOnUpdate = enableChangeInsertOnUpdate;
    }

    public Boolean getEnableUserUUIDOnUpdate() {
        return enableUserUUIDOnUpdate;
    }

    public void setEnableUserUUIDOnUpdate(Boolean enableUserUUIDOnUpdate) {
        this.enableUserUUIDOnUpdate = enableUserUUIDOnUpdate;
    }

    public Boolean getEnableUserUniqueDelete() {
        return enableUserUniqueDelete;
    }

    public void setEnableUserUniqueDelete(Boolean enableUserUniqueDelete) {
        this.enableUserUniqueDelete = enableUserUniqueDelete;
    }
}
